import { Controller, Post, Body, Get, Query, Logger } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBody, ApiQuery, ApiProperty } from '@nestjs/swagger';
import { PrettyAddressService, PrettyAddressConfig } from '../services/pretty-address.service';
import { IsString, IsOptional, IsBoolean, IsNumber, Min, Max, Length } from 'class-validator';
import { Transform, Type } from 'class-transformer';

class GeneratePrettyAddressDto {
  @ApiProperty({
    description: 'Address prefix',
    example: '123',
    required: false,
  })
  @IsOptional()
  @IsString()
  @Length(0, 10)
  prefix?: string;

  @ApiProperty({
    description: 'Address suffix',
    example: '999',
    required: false,
  })
  @IsOptional()
  @IsString()
  @Length(0, 10)
  suffix?: string;

  @ApiProperty({
    description: 'Case sensitive matching',
    example: false,
    required: false,
  })
  @IsOptional()
  @IsBoolean()
  @Transform(({ value }) => value === 'true' || value === true)
  caseSensitive?: boolean;

  @ApiProperty({
    description: 'Number of threads for generation',
    example: 1,
    minimum: 1,
    maximum: 16,
    required: false,
  })
  @IsOptional()
  @IsNumber()
  @Min(1)
  @Max(16)
  @Type(() => Number)
  threads?: number;

  @ApiProperty({
    description: 'Maximum attempts before giving up',
    example: 1000000,
    required: false,
  })
  @IsOptional()
  @IsNumber()
  @Min(1000)
  @Type(() => Number)
  maxAttempts?: number;
}

@ApiTags('Pretty Address')
@Controller('api/pretty-address')
export class PrettyAddressController {
  private readonly logger = new Logger(PrettyAddressController.name);

  constructor(private readonly prettyAddressService: PrettyAddressService) {}

  @Post('generate')
  @ApiOperation({ summary: 'Generate a pretty Solana address' })
  @ApiBody({ type: GeneratePrettyAddressDto })
  @ApiResponse({
    status: 200,
    description: 'Pretty address generated successfully',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean' },
        data: {
          type: 'object',
          properties: {
            publicKey: { type: 'string' },
            secretKey: { type: 'array', items: { type: 'number' } },
            attempts: { type: 'number' },
            timeElapsed: { type: 'number' },
            difficulty: { type: 'number' }
          }
        }
      }
    }
  })
  @ApiResponse({
    status: 400,
    description: 'Invalid configuration or generation failed'
  })
  async generatePrettyAddress(@Body() config: GeneratePrettyAddressDto) {
    try {
      this.logger.log('Generating pretty address with config:', config);

      // 验证配置
      const validation = this.prettyAddressService.validatePrettyConfig(config);
      if (!validation.valid) {
        return {
          success: false,
          error: validation.message
        };
      }

      // 生成靓号地址
      const result = await this.prettyAddressService.generatePrettyAddress(config);

      if (!result) {
        return {
          success: false,
          error: 'Failed to generate pretty address within timeout. Try reducing prefix/suffix length or increasing threads.'
        };
      }

      return {
        success: true,
        data: result
      };

    } catch (error) {
      this.logger.error('Pretty address generation failed:', error);
      return {
        success: false,
        error: error.message || 'Internal server error'
      };
    }
  }

  @Get('estimate')
  @ApiOperation({ summary: 'Estimate difficulty and time for pretty address generation' })
  @ApiQuery({ name: 'prefix', required: false, description: 'Address prefix' })
  @ApiQuery({ name: 'suffix', required: false, description: 'Address suffix' })
  @ApiQuery({ name: 'caseSensitive', required: false, description: 'Case sensitive matching' })
  @ApiQuery({ name: 'threads', required: false, description: 'Number of threads' })
  @ApiResponse({
    status: 200,
    description: 'Estimation successful',
    schema: {
      type: 'object',
      properties: {
        success: { type: 'boolean' },
        data: {
          type: 'object',
          properties: {
            difficulty: { type: 'number' },
            estimatedTimeSeconds: { type: 'number' },
            estimatedTimeFormatted: { type: 'string' },
            recommendation: { type: 'string' }
          }
        }
      }
    }
  })
  async estimateDifficulty(
    @Query('prefix') prefix?: string,
    @Query('suffix') suffix?: string,
    @Query('caseSensitive') caseSensitive?: string,
    @Query('threads') threads?: string
  ) {
    try {
      const config: PrettyAddressConfig = {
        prefix: prefix || '',
        suffix: suffix || '',
        caseSensitive: caseSensitive === 'true',
        threads: threads ? parseInt(threads) : 1
      };

      // 验证配置
      const validation = this.prettyAddressService.validatePrettyConfig(config);
      if (!validation.valid) {
        return {
          success: false,
          error: validation.message
        };
      }

      const difficulty = this.prettyAddressService.calculateDifficulty(
        config.prefix,
        config.suffix,
        config.caseSensitive
      );

      const estimatedTimeSeconds = this.prettyAddressService.estimateTime(
        difficulty,
        config.threads
      );

      // 格式化时间
      let timeFormatted: string;
      if (estimatedTimeSeconds < 60) {
        timeFormatted = `${estimatedTimeSeconds} 秒`;
      } else if (estimatedTimeSeconds < 3600) {
        timeFormatted = `${Math.ceil(estimatedTimeSeconds / 60)} 分钟`;
      } else if (estimatedTimeSeconds < 86400) {
        timeFormatted = `${Math.ceil(estimatedTimeSeconds / 3600)} 小时`;
      } else {
        timeFormatted = `${Math.ceil(estimatedTimeSeconds / 86400)} 天`;
      }

      // 生成建议
      let recommendation: string;
      if (difficulty <= 1000) {
        recommendation = '难度较低，预计很快完成';
      } else if (difficulty <= 100000) {
        recommendation = '难度适中，建议使用多线程加速';
      } else if (difficulty <= 1000000) {
        recommendation = '难度较高，建议考虑减少字符数量';
      } else {
        recommendation = '难度极高，强烈建议减少前缀/后缀长度';
      }

      return {
        success: true,
        data: {
          difficulty,
          estimatedTimeSeconds,
          estimatedTimeFormatted: timeFormatted,
          recommendation,
          config: {
            prefix: config.prefix,
            suffix: config.suffix,
            caseSensitive: config.caseSensitive,
            threads: config.threads,
            totalLength: (config.prefix?.length || 0) + (config.suffix?.length || 0)
          }
        }
      };

    } catch (error) {
      this.logger.error('Difficulty estimation failed:', error);
      return {
        success: false,
        error: error.message || 'Internal server error'
      };
    }
  }

  @Post('validate')
  @ApiOperation({ summary: 'Validate pretty address configuration' })
  @ApiBody({ type: GeneratePrettyAddressDto })
  @ApiResponse({
    status: 200,
    description: 'Validation result',
    schema: {
      type: 'object',
      properties: {
        valid: { type: 'boolean' },
        message: { type: 'string' },
        details: {
          type: 'object',
          properties: {
            difficulty: { type: 'number' },
            estimatedTime: { type: 'number' },
            characterCheck: { type: 'boolean' },
            lengthCheck: { type: 'boolean' }
          }
        }
      }
    }
  })
  async validateConfig(@Body() config: GeneratePrettyAddressDto) {
    try {
      const validation = this.prettyAddressService.validatePrettyConfig(config);
      const difficulty = this.prettyAddressService.calculateDifficulty(
        config.prefix || '',
        config.suffix || '',
        config.caseSensitive || false
      );
      const estimatedTime = this.prettyAddressService.estimateTime(difficulty, config.threads || 1);

      // 详细检查
      const base58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
      const allCharsValid = (config.prefix || '').split('').concat((config.suffix || '').split(''))
        .every(char => base58Chars.includes(char));
      
      const totalLength = (config.prefix?.length || 0) + (config.suffix?.length || 0);
      const lengthReasonable = totalLength <= 8;

      return {
        valid: validation.valid,
        message: validation.message,
        details: {
          difficulty,
          estimatedTime,
          characterCheck: allCharsValid,
          lengthCheck: lengthReasonable,
          totalLength,
          threadsValid: (config.threads || 1) >= 1 && (config.threads || 1) <= 16
        }
      };

    } catch (error) {
      this.logger.error('Config validation failed:', error);
      return {
        valid: false,
        message: error.message || 'Validation error'
      };
    }
  }
}
